package com.epfresh.api.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Process;


import com.epfresh.api.entity.User;
import com.epfresh.api.helper.ApplicationHelper;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


public class CrashHandler implements UncaughtExceptionHandler {
    private static final String TAG = "CrashHandler";
    private static final boolean DEBUG = true;
    private static boolean isMail = false;

    private static String PATH;
    private static final String FILE_NAME = "crash";

    // log文件的后缀名
    private static final String FILE_NAME_SUFFIX = ".txt";

    private static CrashHandler sInstance = new CrashHandler();

    // 系统默认的异常处理（默认情况下，系统会终止当前的异常程序）
    private UncaughtExceptionHandler mDefaultCrashHandler;

    private Context mContext;
    // 额外需要记录的信息，比如注册用户名等
    private Object extra;

    // 构造方法私有，防止外部构造多个实例，即采用单例模式
    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        return sInstance;
    }

    // 这里主要完成初始化工作
    public void init(Context context, Object extra, String url, boolean isMail) {
        // 获取系统默认的异常处理器
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 将当前实例设为系统默认的异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
        // 获取Context，方便内部使用
        mContext = context.getApplicationContext();
        PATH = FileUtil.mAvailableRootWithDecoratePath + "/log/";
        this.extra = extra;
        this.isMail = isMail;
        if (isMail)
            initMail();
    }

    // 这里主要完成初始化工作
    public void init(Context context) {
        init(context, null, null, false);
    }

    /**
     * 这个是最关键的函数，当程序中有未被捕获的异常，系统将会自动调用#uncaughtException方法
     * thread为出现未捕获异常的线程，ex为未捕获的异常，有了这个ex，我们就可以得到异常信息。
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        try {
            // 导出异常信息到SD卡中

            L.e("MobclickAgent", ex.toString());
            dumpExceptionToSDCard(ex);
            // 这里可以通过网络上传异常信息到服务器，便于开发人员分析日志从而解决bug
            uploadExceptionToServer();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 打印出当前调用栈信息
        ex.printStackTrace();

        // 如果系统提供了默认的异常处理器，则交给系统去结束我们的程序，否则就由我们自己结束自己
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, ex);
        } else {
            Process.killProcess(Process.myPid());
        }

    }

    private void dumpExceptionToSDCard(Throwable ex) throws IOException {
        // 如果SD卡不存在或无法使用，则无法把异常信息写入SD卡
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            if (DEBUG) {
                L.w(TAG, "sdcard unmounted,skip dump exception");
                return;
            }
        }

        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        if (!dir.exists()) {
            dir.mkdir();
        }
        long current = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINESE).format(new Date(current));
        // 以当前时间创建log文件
        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
        if (!file.exists()) {
            file.createNewFile();
        }

        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            if (extra != null) {
                // 导出发生异常的额外信息
                pw.println(extra.toString());
            }
            // 导出发生异常的时间
            pw.println(time);

            // 导出手机信息
            dumpPhoneInfo(pw);

            pw.println();
            // 导出异常的调用栈信息
            ex.printStackTrace(pw);

            pw.close();

            if (isMail) {
                SharedPreferences sp = FileUtil.getBugSharedPreferences();
                String content = sp.getString("content", "");
                content += "," + time;
                SharedPreferences.Editor edit = sp.edit();
                edit.putString("content", content);
                edit.commit();
            }
        } catch (Exception e) {
            L.e(TAG, "dump crash info failed");
        }
    }

    @SuppressWarnings("deprecation")
    private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {
        // 应用的版本名称和版本号
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        pw.print("App Version: ");
        pw.print(pi.versionName);
        pw.print('_');
        pw.println(pi.versionCode);

        // android版本号
        //os
        pw.print("OS Version: ");
        pw.print(Build.VERSION.RELEASE);
        pw.print("_");
        pw.println(Build.VERSION.SDK_INT);

        // 手机制造商
        //vendor
        pw.print("Vendor: ");
        pw.println(Build.MANUFACTURER);

        // 手机型号
        //
        pw.print("Model: ");
        pw.println(Build.MODEL);

        // cpu架构
        pw.print("CPU ABI: ");
        pw.println(Build.CPU_ABI);
        pw.print("PRODUCT: ");
        pw.println(Build.PRODUCT);
        pw.print("BRAND: ");
        pw.println(Build.BRAND);
        User user = ApplicationHelper.getInstance().getUser();
        if (user != null) {
            pw.print("USER: ");
            pw.println(user.getNickname());
            pw.print("PHONE: ");
            pw.println(user.getPhone());
        }
    }

    private String getDeviceInfo() {
        StringBuilder sb = new StringBuilder();
        try {
            // 应用的版本名称和版本号
            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
            sb.append("packageName: " + pi.packageName + "\n");
            sb.append("appVersion: " + pi.versionName + "\n");
            sb.append("codeVersion: " + pi.versionCode + "\n");
            sb.append("oSVersion: " + Build.VERSION.RELEASE + "\n");
            sb.append("oSVersionInt: " + Build.VERSION.SDK_INT + "\n");
            sb.append("vendor: " + Build.MANUFACTURER + "\n");
            sb.append("model: " + Build.MODEL + "\n");
            sb.append("CPU ABI: " + Build.CPU_ABI + "\n");
            sb.append("PRODUCT: " + Build.PRODUCT + "\n");
            sb.append("BRAND: " + Build.BRAND + "\n");
            sb.append("CPU ABI: " + Build.CPU_ABI + "\n");


            User user = ApplicationHelper.getInstance().getUser();
            if (user != null) {

                sb.append("USER: " + user.getNickname() + "\n");
                sb.append("PHONE: " + user.getPhone() + "\n");
            }

        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }


        return sb.toString();
    }

    private String getPackageInfo() {
        StringBuilder sb = new StringBuilder();
        // 应用的版本名称和版本号
        PackageManager pm = mContext.getPackageManager();

        try {
            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
            sb.append("packageName:" + pi.packageName);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }


        return sb.toString();
    }

    private void uploadExceptionToServer() {

    }

    public void uploadExceptionToMailAsync() {

        if (!isMail) {
            return;
        }
        new Thread() {
            @Override
            public void run() {

                uploadExceptionToMails();

            }
        }.start();
    }

    public void uploadExceptionToMails() {
        SharedPreferences sp = FileUtil.getBugSharedPreferences();
        String content = sp.getString("content", "");


        if (content != null && !"".equals(content)) {
            String[] split = content.split(",");
            if (split != null) {
                for (int i = 0; i < split.length; i++) {
                    if (split[i] != null && !"".equals(split[i])) {
                        File file = new File(PATH + FILE_NAME + split[i] + FILE_NAME_SUFFIX);

                        if (file != null && file.exists())
                            uploadExceptionToMail(getPackageInfo(), getDeviceInfo(), file);
                    }
                }
            }
            SharedPreferences.Editor edit = sp.edit();
            edit.putString("content", "");
            edit.commit();

        }


    }


    private String mReceiveEmail;
    private String mSendEmail;
    private String mSendPassword;
    private String mHost;
    private String mPort;

    private void initMail() {

        mReceiveEmail = "epfresh_android@163.com";
        mSendEmail = "epfresh_android@163.com";
        mSendPassword = "epfresh1234";
        mHost = "smtp.163.com";
        mPort = "465";
    }

    private void uploadExceptionToMail(String title, String body, File file) {
        LogMail sender = new LogMail().setUser(mSendEmail).setPass(mSendPassword)
                .setFrom(mSendEmail).setTo(mReceiveEmail).setHost(mHost).setPort(mPort)
                .setSubject(title).setBody(body);

        sender.init();

        try {

            sender.addAttachment(file.getPath(), file.getName());
            sender.send();
//            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
